package com.anji.plus.gaea.job.trigger.dao.entity;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.anji.plus.gaea.job.core.util.ObjectUtil;
import com.anji.plus.gaea.job.trigger.dao.BaseRowMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.RowMapper;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 定时任务执行器注册表 entity
 * @author 木子李*de
 * @date 2023-05-12 15:25:35.961
 **/
public class MetaJobInfo {

    private static Logger logger = LoggerFactory.getLogger(MetaJobInfo.class);

    private Long id;

    /** 租户编码，为空时表示系统级 */
    private String tenantCode;

    /** 机构编码，为空时表示系统级 */
    private String orgCode;

    /** 执行器编码，取自执行器springboot的spring.application.name */
    private String executorCode;

    /** 任务名称 */
    private String jobName;

    /** 任务类型，BEAN/SQL */
    private String jobType;

    /** jobType=BEAN时，存放jobHandler的beanName */
    private String jobHandler;

    /** jobType=SQL时，存放sql */
    private String jobSource;

    /** jobSource更新时间 */
    private Date jobSourceUpdateTime;

    /** 任务--调度类型，NONE/CRON/FIX_RATE固定速度 */
    private String scheduleType;

    /** 任务--调度配置，时间表达式/固定速度 */
    private String scheduleConf;

    /** 任务--调度过期策略，DO_NOTHING忽略/FIRE_ONCE_NOW立即执行一次 */
    private String jobMisfireStrategy;

    /** 任务--路由策略，
     * FIRST第一个/LAST最后一个/ROUND轮询/RANDOM随机/CONSISTENT_HASH一致性HASH/
     * LEAST_FREQUENTLY_USED最不经常使用/LEAST_RECENTLY_USED最近最久未使用/FAILOVER故障转移/BUSYOVER忙碌转移 */
    private String jobRouteStrategy;

    /** 任务--阻塞处理策略，SERIAL_EXECUTION单机串行/DISCARD_LATER丢弃后续调度/COVER_EARLY覆盖之前调度 */
    private String jobBlockStrategy;

    /** 任务--执行器任务参数 */
    private String jobParam;

    /** 在启用getParamList、getTotalCount下，分页处理页大小 */
    private Integer jobBatch;

    /** 任务--执行超时时间，单位秒 */
    private Integer jobTimeout;

    /** 任务--失败重试次数 */
    private Integer jobFailRetryCount;

    /** 任务--调度状态：0-停止，1-运行 */
    private Integer triggerStatus;

    /** 上次调度时间，从1970年1月1日开始计算的总毫秒数 */
    private Long triggerLastTime;

    /** 下次调度时间，从1970年1月1日开始计算的总毫秒数 */
    private Long triggerNextTime;

    /** 子任务ID，多个逗号分隔 */
    private String childJobIds;

    //*********************** getter and setter *************************

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTenantCode() {
        return tenantCode;
    }

    public void setTenantCode(String tenantCode) {
        this.tenantCode = tenantCode;
    }

    public String getOrgCode() {
        return orgCode;
    }

    public void setOrgCode(String orgCode) {
        this.orgCode = orgCode;
    }

    public String getExecutorCode() {
        return executorCode;
    }

    public void setExecutorCode(String executorCode) {
        this.executorCode = executorCode;
    }

    public String getJobName() {
        return jobName;
    }

    public void setJobName(String jobName) {
        this.jobName = jobName;
    }

    public String getJobType() {
        return jobType;
    }

    public void setJobType(String jobType) {
        this.jobType = jobType;
    }

    public String getJobHandler() {
        return jobHandler;
    }

    public void setJobHandler(String jobHandler) {
        this.jobHandler = jobHandler;
    }

    public String getJobSource() {
        return jobSource;
    }

    public void setJobSource(String jobSource) {
        this.jobSource = jobSource;
    }

    public Date getJobSourceUpdateTime() {
        return jobSourceUpdateTime;
    }

    public void setJobSourceUpdateTime(Date jobSourceUpdateTime) {
        this.jobSourceUpdateTime = jobSourceUpdateTime;
    }

    public String getScheduleType() {
        return scheduleType;
    }

    public void setScheduleType(String scheduleType) {
        this.scheduleType = scheduleType;
    }

    public String getScheduleConf() {
        return scheduleConf;
    }

    public void setScheduleConf(String scheduleConf) {
        this.scheduleConf = scheduleConf;
    }

    public String getJobMisfireStrategy() {
        return jobMisfireStrategy;
    }

    public void setJobMisfireStrategy(String jobMisfireStrategy) {
        this.jobMisfireStrategy = jobMisfireStrategy;
    }

    public String getJobRouteStrategy() {
        return jobRouteStrategy;
    }

    public void setJobRouteStrategy(String jobRouteStrategy) {
        this.jobRouteStrategy = jobRouteStrategy;
    }

    public String getJobBlockStrategy() {
        return jobBlockStrategy;
    }

    public void setJobBlockStrategy(String jobBlockStrategy) {
        this.jobBlockStrategy = jobBlockStrategy;
    }

    public String getJobParam() {
        return jobParam;
    }

    public void setJobParam(String jobParam) {
        this.jobParam = jobParam;
    }

    public Integer getJobBatch() {
        return jobBatch;
    }

    public void setJobBatch(Integer jobBatch) {
        this.jobBatch = jobBatch;
    }

    public Integer getJobTimeout() {
        return jobTimeout;
    }

    public void setJobTimeout(Integer jobTimeout) {
        this.jobTimeout = jobTimeout;
    }

    public Integer getJobFailRetryCount() {
        return jobFailRetryCount;
    }

    public void setJobFailRetryCount(Integer jobFailRetryCount) {
        this.jobFailRetryCount = jobFailRetryCount;
    }

    public Integer getTriggerStatus() {
        return triggerStatus;
    }

    public void setTriggerStatus(Integer triggerStatus) {
        this.triggerStatus = triggerStatus;
    }

    public Long getTriggerLastTime() {
        return triggerLastTime;
    }

    public void setTriggerLastTime(Long triggerLastTime) {
        this.triggerLastTime = triggerLastTime;
    }

    public Long getTriggerNextTime() {
        return triggerNextTime;
    }

    public void setTriggerNextTime(Long triggerNextTime) {
        this.triggerNextTime = triggerNextTime;
    }

    public String getChildJobIds() {
        return childJobIds;
    }

    public void setChildJobIds(String childJobIds) {
        this.childJobIds = childJobIds;
    }

    //*********************** getRowMapper *************************
    public static final RowMapper<MetaJobInfo> RowMapper = new BaseRowMapper(MetaJobInfo.class);
    /*
    public static RowMapper<MetaJobInfo> buildRowMapper(){
        return new RowMapper<MetaJobInfo>(){
            @Override
            public MetaJobInfo mapRow(ResultSet rs, int i) throws SQLException {
                MetaJobInfo metaJobInfo = new MetaJobInfo();
                metaJobInfo.setId(rs.getLong("id"));
                metaJobInfo.setTenantCode(rs.getString("tenant_code"));
                metaJobInfo.setOrgCode(rs.getString("org_code"));
                metaJobInfo.setExecutorCode(rs.getString("executor_code"));
                metaJobInfo.setJobName(rs.getString("job_name"));
                metaJobInfo.setScheduleType(rs.getString("schedule_type"));
                metaJobInfo.setScheduleConf(rs.getString("schedule_conf"));
                metaJobInfo.setExecutorMisfireStrategy(rs.getString("executor_misfire_strategy"));
                metaJobInfo.setExecutorRouteStrategy(rs.getString("executor_route_strategy"));
                metaJobInfo.setExecutorBlockStrategy(rs.getString("executor_block_strategy"));
                metaJobInfo.setExecutorHandler(rs.getString("executor_handler"));
                metaJobInfo.setExecutorParam(rs.getString("executor_param"));

                metaJobInfo.setExecutorTimeout(rs.getInt("executor_timeout"));
                metaJobInfo.setExecutorFailRetryCount(rs.getInt("executor_fail_retry_count"));
                metaJobInfo.setTriggerStatus(rs.getInt("trigger_status"));
                metaJobInfo.setTriggerLastTime(rs.getLong("trigger_last_time"));
                metaJobInfo.setTriggerNextTime(rs.getLong("trigger_next_time"));
                metaJobInfo.setCreateBy(rs.getString("create_by"));
                metaJobInfo.setCreateTime(rs.getDate("create_time"));
                metaJobInfo.setUpdateBy(rs.getString("update_by"));
                metaJobInfo.setUpdateTime(rs.getDate("update_time"));
                metaJobInfo.setVersion(rs.getInt("version"));

                return metaJobInfo;
            }
        };
    }
    */
    public String getJobMergedParam() {
        JSONObject json = new JSONObject();
        if(ObjectUtil.isNotBlank(jobParam)){
            try{
                //[{"key":"","value":"","desc":""}]
                JSONArray array = JSONObject.parseArray(jobParam);
                for(int i=0; i< array.size(); i++){
                    JSONObject item = array.getJSONObject(i);

                    String key = item.getString("key");
                    Object value = item.get("value");
                    String valueStr = "";
                    if(value instanceof JSONArray){
                        // 将数组["SR305041","SR305042"]  转换成 “SR305041,SR305042”
                        List<String> values = new ArrayList<String>();
                        JSONArray valueArray = item.getJSONArray("value");
                        for(int j=0; j<valueArray.size(); j++){
                            values.add(valueArray.getString(j));
                        }
                        valueStr = values.stream().collect(Collectors.joining(","));
                    } else {
                        valueStr = String.valueOf(value);
                    }

                    json.put(key, valueStr);
                }
            }catch (Exception e){
                logger.warn("parse jsonarray fail, jobId:{}, jobParam:{}, error:{}", id, jobParam, e);
            }
        }
        json.put("tenantCode", tenantCode);
        json.put("orgCode", orgCode);
        return json.toJSONString();
    }
}
